package service

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	v1 "go-websocket/api/im/v1"
	"go-websocket/internal/dao"
	"go-websocket/internal/model/entity"
	"go-websocket/utility"
)

type loginService struct {}


var Login = new(loginService)

var SessionList = gmap.New(true)


//用户登录
func (s * loginService) UserLogin (r *ghttp.Request, req *v1.UserLoginReq) (token string, err error) {

	var userInfo *entity.TxzhUser
	userModel := dao.TxzhUser.Ctx(context.TODO())
	err = userModel.Where("username", req.UserName).Scan(&userInfo)

	if err != nil {
		g.Log().Error(context.TODO(), err)
		return "", err
	}


	//region
	/*
		// 检查是否包含client_id字段
			value, ok := userInfo["client_id"]
			if !ok {
				fmt.Println("client_id不存在")
				return
			}

			// 使用 reflect 包来获取值的类型
			valueType := reflect.TypeOf(value)

			// 检查类型是否为你期望的类型
			if valueType == reflect.TypeOf(gdb.Value{}) {
				fmt.Println("client_id存在并且类型正确")
			} else {
				fmt.Println("client_id存在但类型不正确")
			}
	*/

	//endregion


	if userInfo != nil && userInfo.ClientId != "" && req.ClientId != ""{
		_, err = userModel.Update(g.Map{"client_id": req.ClientId}, "id", userInfo.Id)
		if err != nil {
			g.Log().Error(context.TODO(), err)
			return "", err
		}
	}

	encrypt, err := gmd5.Encrypt(req.Password)
	if err != nil {
		g.Log().Error(context.TODO(), err)
		return "", err
	}

	//fmt.Printf("=%v", encrypt)
	if userInfo == nil || userInfo.Password != encrypt {
		return "", errors.New("用户名或密码错误")
	}

	if userInfo.Status != 0 {
		return "", errors.New("用户已被"+map[interface{}]string{1:"锁定", 2:"冻结"}[userInfo.Status])
	}

	//登录日志
	loginLogMode := dao.TxzhLoginLog.Ctx(context.TODO())
	_, err = loginLogMode.Insert(g.Map{"user_id": userInfo.Id, "ip": r.GetClientIp(), "details": "账号密码登录", "agent_id": req.AgentId})

	if err != nil {
		return "", err
	}

	token, err = createToken(userInfo.Id)
	if err != nil {
		return "", err
	}

	// 设置SESSION信息
	session := r.Session
	err = session.Set("userId", userInfo.Id)
	if err != nil {
		return "", err
	}
	err = session.Set("userInfo", userInfo)
	if err != nil {
		return "", err
	}
	sessionId, err := session.Id()
	if err != nil {
		return "", err
	}
	SessionList.Set(sessionId, session)
	return token, nil
}



func createToken (userId int) (token string, err error){

	var payload map[string]interface{}

	systemModel := dao.TxzhSystem.Ctx(context.TODO())

	var dbData []*entity.TxzhSystem

	err = systemModel.Where(g.Map{"key": "JWT"}).Scan(&dbData)

	if err != nil {
		return
	}

	mapValue := dbData[0].Value

	var flag bool
	if keyValue, ok := mapValue["key"].(map[string]interface{});ok {
		if keyStr, ok := keyValue["value"].(string); ok {

			utility.Key = keyStr

			if timeValue, ok := mapValue["time"].(map[string]interface{});ok {
				if timeStrTmp, ok := timeValue["value"].(json.Number); ok {
					var timeStrInt int64
					timeStrInt, err = timeStrTmp.Int64()
					if err != nil {
						return
					}
					/*
						对于 int64 到 int 的转换，可以使用 math 包中的常量 math.MaxInt 和 math.MinInt 进行范围检查，以确保转换时不会发生溢出。以下是一个示例：
						package main

						import (
							"fmt"
							"math"
						)

						func main() {
							// 示例 int64 值
							var int64Value int64 = 9223372036854775807 // 最大的 int64 值

							// 范围检查
							if int64Value > math.MaxInt || int64Value < math.MinInt {
								fmt.Println("Error: int64 value is out of int range")
								return
							}

							// 将 int64 转换为 int，通过了范围检查
							intValue := int(int64Value)

							// 输出结果
							fmt.Println("Converted int:", intValue)
						}

					*/
					utility.TimeNum = int(timeStrInt)
					flag = true
				}
			}

		} else {
			return
		}
	} else {
		return
	}

	if flag {
		payload = make(map[string]interface{})
		payload["user_id"] = userId
		return utility.GetToken(payload), nil

	}


	return
}